#include "rgb_spi_drv.h"
#include "sys_param.h"
#include "my_gpio.h"


#define LED_RGB_DISPLAY          0   

#define SPI_MASTER                SPI1
#define SPI_MASTER_CLK            RCC_APB2_PERIPH_SPI1
#define SPI_MASTER_GPIO           GPIOA
#define SPI_MASTER_PIN_MOSI       GPIO_PIN_7


// #define SPI_MASTER_GPIO_CLK       RCC_APB2_PERIPH_GPIOA
// #define SPI_MASTER_PIN_NSS        GPIO_PIN_4
// #define SPI_MASTER_PIN_SCK        GPIO_PIN_5
// #define SPI_MASTER_PIN_MISO       GPIO_PIN_6


// #define SPI_MASTER_Rx_DMA_Channel DMA_CH3
// #define SPI_MASTER_Rx_DMA_FLAG    DMA_FLAG_TC3
// #define SPI_MASTER_Tx_DMA_Channel DMA_CH4
// #define SPI_MASTER_Tx_DMA_FLAG    DMA_FLAG_TC4


// #define SPI_SLAVE_Rx_DMA_Channel DMA_CH1
// #define SPI_SLAVE_Rx_DMA_FLAG    DMA_FLAG_TC1
// #define SPI_SLAVE_Tx_DMA_Channel DMA_CH2
// #define SPI_SLAVE_Tx_DMA_FLAG    DMA_FLAG_TC2

// #define SPI_SLAVE_DR_Base           SPI2_BASE+0x0c //0x40013C0C
// #define SPI_MASTER_DR_Base          SPI1_BASE+0x0c //0x4001300C


typedef struct 
{
    uint8_t refresh_cnt;
    uint8_t flicker_flag;
    uint8_t disp_mode;
    uint8_t disp_level;
    uint8_t disp_color;

    /* data */
}RGB_DISPLAY_PARAM_t;

RGB_DISPLAY_PARAM_t rgb_data = {0};

/*

用户可以选择 DMA 进行 SPI 数据传输，应用程序可以得到释放，系统效率可以大大提升。
当发送缓存 DMA 使能（SPI_CTRL2.TDMAEN 位置 1），每次 SPI_STS.TE 标志位置 1，会产生 DMA 请
求，DMA 自动将数据写入 SPI_DAT 寄存器，这将会清除 TE 标志位。当接收缓存 DMA 使能
（SPI_CTRL2.RDMAEN 位置 1），每次 SPI_STS.RNE 标志位置 1，会产生 DMA 请求，DMA 自动读取
SPI_DAT 寄存器，这将会清除 SPI_STS.RNE 标志位。
当 SPI 仅用于数据发送，仅需要使能 SPI 的发送 DMA 通道（SPI_CTRL2.TDMAEN 位置 1）。
当 SPI 仅用于数据接收，仅需要使能 SPI 的接收 DMA 通道（SPI_CTRL2.RDMAEN 位置 1）。
*/

 void ws2812_logic_high(void)
{
   SPI_MASTER_GPIO->PBSC = SPI_MASTER_PIN_MOSI;
}

static void ws2812_logic_low(void)
{
    SPI_MASTER_GPIO->PBC = SPI_MASTER_PIN_MOSI;
}


__inline void spi_delay(int delay_cnt)
{
    int i;
    for(i = 0; i < delay_cnt; i ++){
        __NOP();
    }
}


__inline void black_color(void)
{
#if LED_RGB_DISPLAY    
    int i;
    //  --黑色
    for(i = 0; i < 24 ; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
#endif    
}

__inline void white_color(void)
{
#if LED_RGB_DISPLAY     
    int i;
    //  --白色
    for(i = 0; i < 24 ; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
#endif    
}

__inline void red_color(void)
{
#if LED_RGB_DISPLAY     
    int i;
// --红色
    for(i = 0; i < 8; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
    for(i = 8; i < 16; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
   for(i = 16; i < 24; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
#endif
}

__inline void green_color(void)
{
#if LED_RGB_DISPLAY     
    int i;
// --绿色
    for(i = 0; i < 8; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
    for(i = 8; i < 24; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
#endif
}

__inline void blue_color(void)
{
#if LED_RGB_DISPLAY     
    int i;
// --蓝色
    for(i = 0; i < 16; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
    for(i = 16; i < 24; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
#endif    
}

__inline void purple_color(void)
{
#if LED_RGB_DISPLAY    
    int i;
// --紫色

    for(i = 0; i < 8; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }

    for(i = 8; i < 16; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }

    for(i = 16; i < 24; i++){
        ws2812_logic_high();
        spi_delay(5);
        ws2812_logic_low();
        spi_delay(5);
    }
#endif    
}

__inline void cur_led_on(void)
{
#if LED_RGB_DISPLAY    
    switch(get_sys_rgb_color()){
        case BLACK_COLOR:{
            black_color();
            break;
        }
        case WHITE_COLOR:{
            white_color();
           break; 
        }
        case RED_COLOR:{
            red_color();
           break; 
        }
        case GREEN_COLOR:{
            green_color();
           break; 
        }
        case BLUE_COLOR:{
            blue_color();
           break; 
        }
        default:{
            purple_color();
           break; 
        }
    }
#endif    
}

__inline void cur_led_off(void)
{
#if LED_RGB_DISPLAY    
   int i;

    for(i = 0; i < 24 ; i++){
        ws2812_logic_high();
        __NOP();
        __NOP();
        __NOP();
        ws2812_logic_low();
        spi_delay(5);
    }
#endif
}

/************
 * 主机——提示灯：1颗提示灯、5个档位灯、4颗模式灯[两颗rgb 显示一种模式]
 * 
 *  rgb_index1, 状态指示灯（常亮）
 * 
 *  rgb_index2, （档位1,2）
 *  rgb_index3, （档位3,4）
 *  rgb_index4, （档位5,6）
 *  rgb_index5, （档位7,8）
 *  rgb_index6, （档位9,10）
 * 
 *  rgb_index7,rgb_index8, （模式1）
 *  rgb_index9,rgb_index10, （模式2）
 *  rgb_index11,rgb_index12, （模式3）
 *  rgb_index13,rgb_index14, （模式4）
 * 
*/

/*100ms调用一次*/


void rgb_sip_test(void)
{
#if LED_RGB_DISPLAY

    LEVEL_e level =0;
    WORK_MODE_e state;

// 如果 模式--档位---颜色都相同，则直接退出，不用再刷新rgb
    if((rgb_data.disp_color == get_sys_rgb_color())&&(rgb_data.disp_mode == get_sys_mode())&&(rgb_data.disp_level == get_sys_level())){
        if(0 == get_sys_level()%2){
            if(rgb_data.flicker_flag){
                rgb_data.flicker_flag = 0;
            }
            else{
                return;
            }
        }
    }
    
    // 当前档位为奇数时，进行闪烁
    if(get_sys_level()%2){
        rgb_data.refresh_cnt ++;

        if(rgb_data.refresh_cnt%5 == 0){
            rgb_data.flicker_flag = ~rgb_data.flicker_flag;
            level = get_sys_level();
            if(rgb_data.flicker_flag){
                level --;
            }
        }
        else{
            return;
        }
    }
    else{
        level = get_sys_level();
    }

    //rgb_index1, 状态指示灯（常亮）
    cur_led_on();

    //rgb_index2, （档位1,2）------5颗档位灯
    if(level > LEVEL_0){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
    //rgb_index3, （档位3,4）
    if(level > LEVEL_2){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
    //  rgb_index4, （档位5,6）
    if(level > LEVEL_4){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
    // rgb_index5, （档位7,8）
   if(level > LEVEL_6){
        cur_led_on();
    }
    else{
        cur_led_off();
    }
    // rgb_index6, （档位9,10）
   if(level > LEVEL_8){
        cur_led_on();
    }
    else{
        cur_led_off();
    }



    // --------------模式灯

//  *  rgb_index7,rgb_index8, （模式1）
//  *  rgb_index9,rgb_index10, （模式2）
//  *  rgb_index11,rgb_index12, （模式3）
//  *  rgb_index13,rgb_index14, （模式4）

    state = get_sys_mode();
    switch(state){
        case EYE_MODE:{
            cur_led_on();
            cur_led_on();
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_off();

            break;
        }
        case FACE_MODE:{
            cur_led_off();
            cur_led_off();
            cur_led_on();
            cur_led_on();
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_off();
            break;
        }
        case BODY_MODE:{
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_on();
            cur_led_on();
            cur_led_off();
            cur_led_off();
            break;
        }
        case HAIR_MODE:{
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_off();
            cur_led_on();
            cur_led_on();
            break;
        }
        default:{
            cur_led_on();
            cur_led_off();
            cur_led_on();
            cur_led_off();
            cur_led_on();
            cur_led_off();
            cur_led_on();
            cur_led_off();
            break;
        }
    }

    printf("rgb_level:[%d]\r\n", level);

    rgb_data.disp_color = get_sys_rgb_color();
    rgb_data.disp_mode = get_sys_mode();
    rgb_data.disp_level == get_sys_level();
#endif
}

/********
 * 暂时没有用到reset， 测试时发现将reset拉低后，led显示仍然能够保持，所以reset几乎作用
 * 
*/
void rgb_reset(void)
{
#if LED_RGB_DISPLAY    
    ws2812_logic_low();
#endif    
}


void my_rgb_init(void)
{
#if LED_RGB_DISPLAY    
    gpio_output_cfg(SPI_MASTER_GPIO, SPI_MASTER_PIN_MOSI);
#endif    
}